using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;
using System.Windows.Input;
using System.Diagnostics.Contracts;
using System.Diagnostics.CodeAnalysis;

namespace Granite.Testing
{
	/// <summary>
	/// Assertions for ICommand
	/// </summary>
	public class CommandEventAssert : EventAssert<EventArgs>
	{
		readonly ICommand m_Source;

		/// <summary>
		/// Creates a new ICommand assertion
		/// </summary>
		/// <param name="source"></param>
		public CommandEventAssert(ICommand source)
			: base(source)
		{
			if (source == null)
				throw new ArgumentNullException("source", "source is null.");
			Contract.EndContractBlock();

			m_Source = source;
			m_Source.CanExecuteChanged += SourceEventFired;
		}

		/// <summary>
		/// Asserts that an event is in the queue and that it has the indicated properties.
		/// </summary>
		/// <param name="expectedResult">Expected result from calling CanExecute(commandParameter)</param>
		/// <param name="commandParameter">Parameter to pass to CanExecute</param>
		/// <returns>This will remove the event from the queue.</returns>
		public EventPair<EventArgs> Expect(bool expectedResult, object commandParameter = null)
		{
			var nextEvent = Expect();
			Assert.AreEqual(expectedResult, m_Source.CanExecute(commandParameter));
			return nextEvent;
		}

		[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic"), SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		[ContractInvariantMethod]
		void ObjectInvariant()
		{
			Contract.Invariant(m_Source != null);
		}
	}
}
